package com.niiwoo.civet.user.service.local.sms;

import com.alibaba.dubbo.config.annotation.Reference;
import com.niiwoo.civet.system.service.SysParamService;
import com.niiwoo.civet.user.constants.LoginAccountErrorCode;
import com.niiwoo.civet.user.dto.request.RefreshSMSCodeRequestDTO;
import com.niiwoo.civet.user.enums.UserSMSTypeEnum;
import com.niiwoo.tripod.provider.exception.BizException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.annotation.PostConstruct;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SMSSenders implements ApplicationContextAware {

    private final Map<UserSMSTypeEnum, AbstractSMSSender> SENDERS_MAP = new HashMap<>();

    @Reference(version = "1.0.0")
    private SysParamService sysParamService;

    private ApplicationContext ctx;

    public SMSResult send(RefreshSMSCodeRequestDTO requestDTO) {
        return this.getAppropriateSender(requestDTO.getSmsType()).sendSMS(requestDTO);
    }

    public void removeAuthCodeCache(UserSMSTypeEnum type, String mobileNo) {
        this.getAppropriateSender(type).removeAuthCodeCache(mobileNo);
    }

    public void removeDayTimesCache(UserSMSTypeEnum type, String mobileNo) {
        this.getAppropriateSender(type).removeAuthCodeCache(mobileNo);
    }

    public void removeMonthTimesCache(UserSMSTypeEnum type, String mobileNo) {
        this.getAppropriateSender(type).removeAuthCodeCache(mobileNo);
    }

    /**
     * 校验
     *
     * @param type 短信类型
     * @param mobileNo 手机号码
     * @param exceptCode 验证码
     */
    public boolean isAuthCodeCacheRight(UserSMSTypeEnum type, String mobileNo, String exceptCode) {
        return this.getAppropriateSender(type).isAuthCodeCacheRight(mobileNo, exceptCode);
    }


    private AbstractSMSSender getAppropriateSender(UserSMSTypeEnum type) {
        return Optional.ofNullable(SENDERS_MAP.get(type)).orElseThrow(() -> new BizException(LoginAccountErrorCode.UNKNOWN_SMS_TYPE));
    }


    @PostConstruct
    public void initSenders() {
        Optional.ofNullable(ctx.getBeansOfType(AbstractSMSSender.class))
                .map(Map::values)
                .ifPresent(list -> list.forEach(t -> {
                    t.setSysParamService(sysParamService);
                    SENDERS_MAP.put(t.getType(), t);
                }));
    }

    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        if (ctx.getParent() == null) {
            this.ctx = ctx;
        }
    }


}
